/**
 * Copyright © 2016-2025 The Thingsboard Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.terracloud.server.service.log;

import com.terracloud.server.common.data.log.PlatformLog;
import com.terracloud.server.common.data.id.TenantId;
import com.terracloud.server.common.data.id.UserId;
import com.terracloud.server.common.data.id.PlatformLogId;
import com.terracloud.server.common.data.log.LogLevel;
import com.terracloud.server.common.data.log.LogType;
import com.terracloud.server.common.data.log.PlatformStatistics;
import com.terracloud.server.common.data.page.TimePageLink;
import com.terracloud.server.dao.log.PlatformLogDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;

/**
 * 平台日志服务默认实现
 */
@Service
@Slf4j
public class DefaultPlatformLogService implements PlatformLogService {

    @Autowired
    private PlatformLogDao platformLogDao;

    @Override
    @Transactional
    public PlatformLog savePlatformLog(PlatformLog platformLog) {
        log.trace("Executing savePlatformLog [{}]", platformLog);
        return platformLogDao.save(platformLog);
    }

    @Override
    @Transactional(readOnly = true)
    public PlatformLog findPlatformLogById(PlatformLogId platformLogId) {
        log.trace("Executing findPlatformLogById [{}]", platformLogId);
        return platformLogDao.findById(platformLogId);
    }

    @Override
    @Transactional
    public void deletePlatformLog(PlatformLogId platformLogId) {
        log.trace("Executing deletePlatformLog [{}]", platformLogId);
        platformLogDao.removeById(platformLogId);
    }

    @Override
    @Transactional(readOnly = true)
    public com.terracloud.server.common.data.page.PageData<PlatformLog> findPlatformLogsByTenantId(TenantId tenantId, TimePageLink pageLink) {
        log.trace("Executing findPlatformLogsByTenantId [{}]", tenantId);
        return platformLogDao.findByTenantId(tenantId, pageLink);
    }

    @Override
    @Transactional(readOnly = true)
    public com.terracloud.server.common.data.page.PageData<PlatformLog> findPlatformLogsByTenantIdAndUserId(TenantId tenantId, UserId userId, TimePageLink pageLink) {
        log.trace("Executing findPlatformLogsByTenantIdAndUserId [{}][{}]", tenantId, userId);
        return platformLogDao.findByTenantIdAndUserId(tenantId, userId, pageLink);
    }

    @Override
    @Transactional(readOnly = true)
    public com.terracloud.server.common.data.page.PageData<PlatformLog> findPlatformLogsByTenantIdAndType(TenantId tenantId, LogType logType, TimePageLink pageLink) {
        log.trace("Executing findPlatformLogsByTenantIdAndType [{}][{}]", tenantId, logType);
        return platformLogDao.findByTenantIdAndType(tenantId, logType, pageLink);
    }

    @Override
    @Transactional(readOnly = true)
    public com.terracloud.server.common.data.page.PageData<PlatformLog> findPlatformLogsByTenantIdAndLevel(TenantId tenantId, LogLevel logLevel, TimePageLink pageLink) {
        log.trace("Executing findPlatformLogsByTenantIdAndLevel [{}][{}]", tenantId, logLevel);
        return platformLogDao.findByTenantIdAndLevel(tenantId, logLevel, pageLink);
    }

    @Override
    @Transactional(readOnly = true)
    public long getTodayBusinessOperationCount(TenantId tenantId) {
        log.trace("Executing getTodayBusinessOperationCount [{}]", tenantId);
        // 计算今天的开始和结束时间
        LocalDate today = LocalDate.now();
        long startTime = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant()).getTime();
        long endTime = Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant()).getTime();
        
        TimePageLink pageLink = new TimePageLink(1, 0, null, null, startTime, endTime);
        com.terracloud.server.common.data.page.PageData<PlatformLog> pageData = 
            platformLogDao.findByTenantIdAndType(tenantId, LogType.BUSINESS_LOG, pageLink);
        
        return pageData.getTotalElements();
    }

    @Override
    @Transactional(readOnly = true)
    public long getSensitiveOperationCount(TenantId tenantId) {
        log.trace("Executing getSensitiveOperationCount [{}]", tenantId);
        return platformLogDao.countBySensitiveOperation(tenantId, true);
    }

    @Override
    @Transactional(readOnly = true)
    public double getPermissionChangeRatio(TenantId tenantId) {
        log.trace("Executing getPermissionChangeRatio [{}]", tenantId);
        long totalCount = platformLogDao.findByTenantId(tenantId, new TimePageLink(1, 0, null, null, null, null)).getTotalElements();
        long permissionChangeCount = platformLogDao.countBySensitiveOperation(tenantId, true);
        
        if (totalCount == 0) {
            return 0.0;
        }
        
        return ((double)permissionChangeCount / totalCount) * 100;
    }

    @Override
    @Transactional(readOnly = true)
    public long getUnprocessedExceptionCount(TenantId tenantId) {
        log.trace("Executing getUnprocessedExceptionCount [{}]", tenantId);
        // 这里假设状态为"未处理"的异常日志即为未处理异常
        // 实际实现应根据具体业务需求调整
        return platformLogDao.countByStatus(tenantId, "未处理");
    }

    @Override
    @Transactional(readOnly = true)
    public long getCriticalExceptionCount(TenantId tenantId) {
        log.trace("Executing getCriticalExceptionCount [{}]", tenantId);
        TimePageLink pageLink = new TimePageLink(1, 0, null, null, null, null);
        com.terracloud.server.common.data.page.PageData<PlatformLog> pageData = 
            platformLogDao.findByTenantIdAndLevel(tenantId, LogLevel.CRITICAL, pageLink);
        
        return pageData.getTotalElements();
    }

    @Override
    @Transactional(readOnly = true)
    public long getActiveUserOperationCount(TenantId tenantId) {
        log.trace("Executing getActiveUserOperationCount [{}]", tenantId);
        // 这里只是一个示例实现，实际应该根据业务逻辑计算活跃用户操作数量
        // 比如：统计一段时间内有操作记录的用户数
        return platformLogDao.findByTenantId(tenantId, new TimePageLink(1, 0, null, null, null, null)).getTotalElements();
    }

    @Override
    @Transactional(readOnly = true)
    public PlatformStatistics getPlatformStatistics(TenantId tenantId) {
        log.trace("Executing getPlatformStatistics [{}]", tenantId);
        long todayBusinessOperationCount = getTodayBusinessOperationCount(tenantId);
        long sensitiveOperationCount = getSensitiveOperationCount(tenantId);
        double permissionChangeRatio = getPermissionChangeRatio(tenantId);
        long unprocessedExceptionCount = getUnprocessedExceptionCount(tenantId);
        long criticalExceptionCount = getCriticalExceptionCount(tenantId);
        long activeUserOperationCount = getActiveUserOperationCount(tenantId);
        
        return new PlatformStatistics(todayBusinessOperationCount, sensitiveOperationCount, 
                permissionChangeRatio, unprocessedExceptionCount, criticalExceptionCount, activeUserOperationCount);
    }
}